from django.shortcuts import render
from django.views import View
from homes.models import Area, House, Facility, HouseImage
from order.models import Order
from django.http import JsonResponse
from django.core.cache import cache
from ihome.utils.views import LoginRequiredJsonMixin
from django.core.paginator import Paginator
from django.db import transaction
from ihome.libs.qiniu_demo import QiNiu
from ihome.utils.image_check import image_checking
import json, logging, datetime

logger = logging.getLogger('ihome')
url = "http://qs930d3tn.hn-bkt.clouddn.com/"    # 图片的链接头


class ListAreas(View):
    """城区列表"""

    def get(self, requset):
        area_list = cache.get("area_list")
        if area_list is None:
            try:
                area_model_list = Area.objects.all()
                area_list = []
                for area_model in area_model_list:
                    area_list.append({
                        "aid": area_model.id,
                        "aname": area_model.name,
                    })
            except Exception as e:
                logger.error(e)
                return JsonResponse({"errno": 4001, "errmsg": "获取失败"})
            cache.set("area_list", area_list, 180)

        return JsonResponse({"errno": 0, "errmsg": "获取成功", "data": area_list})


# class ReleaseHouses(LoginRequiredJsonMixin, View):
class ReleaseHouses(View):
    """发布房源、搜索房源信息"""

    # 发布房源
    def post(self, request):
        # 1、接收参数
        user = request.user
        json_dict = json.loads(request.body.decode("utf-8"))
        title = json_dict.get("title")
        price = json_dict.get("price")
        area_id = json_dict.get("area_id")
        address = json_dict.get("address")
        room_count = json_dict.get("room_count")
        acreage = json_dict.get("acreage")
        unit = json_dict.get("unit")
        capacity = json_dict.get("capacity")
        beds = json_dict.get("beds")
        deposit = json_dict.get("deposit")
        min_days = json_dict.get("min_days")
        max_days = json_dict.get("max_days")
        facility = json_dict.get("facility")

        # 2、校验参数
        if not all(
                [title, price, area_id, address, room_count, acreage, unit, capacity, beds, deposit, min_days, max_days,
                 facility]):
            return JsonResponse({'errno': 4002, 'errmsg': '缺少必传参数'})
        try:
            area = Area.objects.get(id=area_id)
        except Exception as e:
            logger.error(e)
            return JsonResponse({'errno': 4103, 'errmsg': "参数area_id有误"})

        # 3、业务处理 - 新增房屋信息入表
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                house = House.objects.create(
                    user=user,
                    area=area,
                    title=title,
                    price=price,
                    address=address,
                    room_count=room_count,
                    acreage=acreage,
                    unit=unit,
                    capacity=capacity,
                    beds=beds,
                    deposit=deposit,
                    min_days=min_days,
                    max_days=max_days
                )
                for facility_id in facility:
                    iteam = Facility.objects.get(id=facility_id)
                    house.facility.add(iteam)

            except Exception as e:
                logger.error(e)
                transaction.savepoint_rollback(save_id)
                return JsonResponse({"errno": 4004, "errmsg": "发布房源失败"})
            transaction.savepoint_commit(save_id)

        # 4、响应返回
        return JsonResponse({"errno": 0, "errmsg": "发布房源成功", "data": {"house_id": house.id}})

    # 搜索房源
    def get(self, request):
        # 1、获取参数
        area_id = request.GET.get("aid", "")
        start_day_str = request.GET.get("sd", "")
        end_day_str = request.GET.get("ed", "")
        sort_key = request.GET.get("sk", "new")  # new(新到旧), booking(订单量), price-inc(低到高), price-des(高到低),
        page = request.GET.get("p", 1)

        # 2、校验参数，对日期进行处理
        start_date = None
        end_date = None
        if start_day_str:
            # 字符串形式的日期 转换成 日期类型
            start_date = datetime.date(*map(int, start_day_str.split('-')))
        if end_day_str:
            # 字符串形式的日期 转换成 日期类型
            end_date = datetime.date(*map(int, end_day_str.split('-')))
        if start_date and end_date:
            # 如果开始时间大于或者等于结束时间,就报错
            # assert（断言）用于判断一个表达式，在表达式条件为 false 的时候触发异常。
            assert (start_date < end_date), Exception("开始时间不可大于结束时间")

        # 3、业务处理
        # 3.1、初始化filter筛选集合
        filters = {}
        if area_id:
            # 如果用户有选择区域，再筛选集合列表中添加
            filters["area_id"] = area_id
        # 3.2、找出日期冲突的订单，并获得冲突订单的房间id
        if start_date and end_date:
            # 如过输入了开始和结束日期，冲突订单：订单的开始时间 < 结束时间 and 订单的结束时间 > 开始时间
            conflict_order = Order.objects.filter(begin_date__lt=end_date, end_date__gt=start_date)
        elif start_date:
            # 如果用户只输入了开始时间，冲突订单：订单的开始时间 < 开始时间 < 订单的结束时间
            conflict_order = Order.objects.filter(begin_date__lt=start_date, end_date__gt=start_date)
        elif end_date:
            # 如果用户只输入了结束时间，冲突订单：订单的开始时间 < 结束时间 < 订单的结束时间
            conflict_order = Order.objects.filter(begin_date__lt=end_date, end_date__gt=end_date)
        else:
            conflict_order = []
        conflict_house_id = [order_model.house.id for order_model in conflict_order]
        if conflict_house_id:
            # 如果有找到日期冲突订单，筛选掉存在冲突的房源
            house_id = House.objects.exclude(id_in=conflict_house_id)
            # 添加filter筛选集合
            filters["id_in"] = house_id

        # 3.3、开始查询房源，并按要求排序
        if sort_key == "new":
            house_model = House.objects.filter(**filters).order_by("-create_time")  # new(新到旧)
        elif sort_key == "booking":
            house_model = House.objects.filter(**filters).order_by("-order_count")  # booking(订单量)
        elif sort_key == "price-inc":
            house_model = House.objects.filter(**filters).order_by("price")     # price-inc(低到高)
        elif sort_key == "price-des":
            house_model = House.objects.filter(**filters).order_by("-price")    # price-des(高到低)

        # 3.4、进行分页
        # Paginator：第一个参数是被分页的查询集；第二个参数是每页几个划分
        paginator = Paginator(house_model, 2)
        try:
            page_house_model = paginator.page(page)
        except Exception as e:
            logger.error(e)
            return JsonResponse({"errno": 4004, "errmsg": "页面不存在"})
        # 分页器对象中属性num_pages，总页数
        total_page = paginator.num_pages

        # 4、响应返回
        houses = []
        for n_house in page_house_model:
            houses.append({
                "address": n_house.address,
                "area_name": n_house.area.name,
                "ctime": n_house.create_time.strftime('%Y-%m-%d'),
                "house_id": n_house.id,
                "img_url": url + str(n_house.index_image_url),
                "order_count": n_house.order_count,
                "price": n_house.price,
                "room_count": n_house.room_count,
                "title": n_house.title,
                "user_avatar": url + str(n_house.user.avatar)
            })
        return JsonResponse({"errno": 0, "errmsg": "请求成功", "data": {"houses": houses, "total_page": total_page}})


class UploadHouseImages(LoginRequiredJsonMixin, View):
    """"上传房源图片"""

    def post(self, request, house_id):
        # 1、接收参数
        house_image = request.FILES.get("house_image")  # 获取图片

        # 2、校验参数
        # 2.1、校验图片是否上传
        if house_image is None:
            return JsonResponse({"errno": 4002, "errmsg": "未上传图片"})
        # 2.2、校验上传文件是否是图片
        if image_checking(house_image) is None:
            return JsonResponse({"errno": 4002, "errmsg": "图片格式不正确"})
        # 2.3、校验房源是否存在
        try:
            house_model = House.objects.get(id=house_id)
        except Exception as e:
            logger.error(e)
            return JsonResponse({"errno": 4001, "errmsg": "房间不存在"})

        # 3、业务处理
        image_byte = house_image.read()     # 将图片转换成byte
        key_str = "ihome/houses/image/" + str(house_id) + datetime.datetime.now().strftime("/%Y%m%d%H%M%S")
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                # 上传图片并获取
                image_url = QiNiu().upload_data(key_str, image_byte)
                # 如果房源没有主图片则添加
                a = house_model.index_image_url
                if not house_model.index_image_url:
                    house_model.index_image_url = image_url
                    house_model.save()
                # 将图片记录到房源图片表
                houseimage_model = HouseImage()
                houseimage_model.url = image_url
                houseimage_model.house = house_model
                houseimage_model.save()
            except Exception as e:
                logger.error(e)
                transaction.savepoint_rollback(save_id)
                return JsonResponse({"errno": 4003, "errmsg": "房屋主图片上传失败"})
            transaction.savepoint_commit(save_id)

        # 4. 响应返回
        data = {"url": url + image_url}
        return JsonResponse({"errno": 0, "errmsg": "图片上传成功", "data": data})


class ShowUserHouses(LoginRequiredJsonMixin, View):
    """"展示用户房源列表"""

    def get(self, request):
        user = request.user
        try:
            houses_model_list = House.objects.filter(user_id=user.id).order_by("-create_time")
            houses_list = []
            for house in houses_model_list:
                houses_list.append({
                    "house_id": house.id,
                    "order_count": house.order_count,
                    "title": house.title,
                    "ctime": house.create_time.strftime('%Y-%m-%d'),
                    "price": house.price,
                    "area_name": house.area.name,
                    "address": house.address,
                    "room_count": house.room_count,
                    "img_url": url + str(house.index_image_url),
                    "user_avatar": url + str(house.user.avatar)
                })
                print(house.price)
        except Exception as e:
            logger.error(e)
            return JsonResponse({"errno": 4001, "errmsg": "房源信息出错"})
        return JsonResponse({"errno": 0, "errmsg": "用户房源获取成功", "data": {"houses": houses_list}})


class HotHosesView(View):
    """首页房源推荐"""

    def get(self, request):
        try:
            houses_model_list = House.objects.all().order_by("-order_count")[0: 5:1]
        except Exception as e:
            logger.error(e)
            return JsonResponse({"errno": 4001, "errmsg": "获取房源出错"})
        houses_list = []
        for houses in houses_model_list:
            houses_list.append({
                "house_id": houses.id,
                "img_url": url + str(houses.index_image_url),
                "title": houses.title,
            })
        return JsonResponse({"errno": 0, "errmsg": "获取推荐房源成功", "data": houses_list})


class HouseInfoView(View):
    """房屋详情页面"""

    def get(self, request, house_id):
        user = request.user
        house_model = House.objects.get(id=house_id)
        if user.is_authenticated:
            user_id = user.id
        else:
            user_id = -1

        comments = []
        order_model_list = Order.objects.filter(house_id=house_id, status=4)
        for order in order_model_list:
            comments.append({
                "comment": order.comment,
                "ctime": order.update_time.strftime('%Y-%m-%d %H-%M-%S'),
                "user_name": order.user.username
            })

        facilities = []
        facilities_model = house_model.facility.all()
        for facility in facilities_model:
            facilities.append(facility.id)

        img_urls = []
        for image in house_model.houseimage_set.all():
            img_urls.append(url + str(image.url))

        house = {
            "acreage": house_model.acreage,
            "address": house_model.address,
            "beds": house_model.beds,
            "capacity": house_model.capacity,
            "comments": comments,
            "deposit": house_model.deposit,
            "facilities": facilities,
            "hid": house_model.id,
            "img_urls": img_urls,
            "max_days": house_model.max_days,
            "min_days": house_model.min_days,
            "price": str(house_model.price),
            "room_count": house_model.room_count,
            "title": house_model.title,
            "unit": house_model.unit,
            "user_avatar": url + str(house_model.user.avatar),
            "user_id": str(house_model.user.id),
            "user_name": house_model.user.username
        }

        return JsonResponse({
            "errno": 0,
            "errmsg": "OK",
            "data": {
                "user_id": user_id,
                "house": house
            },
        })
